#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <string.h>  
#include <sys/select.h> 

#define ARGS_CHECK(argc, num)               \  
    do {                                    \  
        if (argc != num) {                  \  
            fprintf(stderr, "Args error!\n"); \  
            return -1;                      \  
        }                                   \  
    } while (0)  
  
#define ERROR_CHECK(ret, num, msg) \  
    do {                             \  
        if (ret == num) {            \  
            perror(msg);             \  
            exit(1);                 \  
        }                            \  
    } while (0)  
  
int main(int argc, char *argv[])  
{  
    ARGS_CHECK(argc, 1);  
  
    int fd1[2];  
    ERROR_CHECK(-1, pipe(fd1), "pipe1");  
  
    int fd2[2];  
    ERROR_CHECK(-1, pipe(fd2), "pipe2");  
  
    char buf[32] = {0};  
    char buf1[32] = {0};  
    pid_t pid = fork();  
    fd_set rw_set;  
  
    if (pid > 0) {  
        // Parent process  
        while (1) {  
            FD_ZERO(&rw_set);  
            FD_SET(STDIN_FILENO, &rw_set);  
            FD_SET(fd1[0], &rw_set);  
            struct timeval timeout = {20, 0};  
            int rw_ret = select(fd1[0] + 1, &rw_set, NULL, NULL, &timeout);  
            if (rw_ret == 0) {  
                puts("Timeout");  
                continue;  
            }  
            if (FD_ISSET(fd1[0], &rw_set)) {  
                memset(buf, 0, sizeof(buf));  
                int ret = read(fd1[0], buf, sizeof(buf) - 1);  
                if (ret <= 0) break;  
                printf("Msg from pipe1: %s", buf);  
            }  
            if (FD_ISSET(STDIN_FILENO, &rw_set)) {  
                memset(buf1, 0, sizeof(buf1));  
                int ret = read(STDIN_FILENO, buf1, sizeof(buf1) - 1);  
                if (ret <= 0) {  
                    write(fd2[1], "over!", 5);  
                    close(fd1[0]);  
                    close(fd1[1]);  
                    close(fd2[0]);  
                    close(fd2[1]);  
                    break;  
                }  
                write(fd2[1], buf1, strlen(buf1));  
                printf("Msg from stdin: %s", buf1);  
            }  
        }  
    } else if (pid == 0) {  
        // Child process  
        while (1) {  
            FD_ZERO(&rw_set);  
            FD_SET(fd2[0], &rw_set);  
            struct timeval timeout = {20, 0};  
            int rw_ret = select(fd2[0] + 1, &rw_set, NULL, NULL, &timeout);  
            if (rw_ret == 0) {  
                puts("Timeout");  
                continue;  
            }  
            if (FD_ISSET(fd2[0], &rw_set)) {  
                memset(buf, 0, sizeof(buf));  
                int ret = read(fd2[0], buf, sizeof(buf) - 1);  
                if (ret <= 0) break;  
                printf("Msg from pipe2: %s", buf);  
            }  
           
        }  
        close(fd1[0]);  
        close(fd1[1]);  
        close(fd2[0]);  
        close(fd2[1]);  
    } else {  
        perror("fork");  
        exit(1);  
    }  
  
    return 0;  
}